package com.springboot.springbootlogindemo.scheduler;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.springboot.springbootlogindemo.DTO.UserLikCountDTO;
import com.springboot.springbootlogindemo.DTO.UserLikesDto;
import com.springboot.springbootlogindemo.domain.ContentStats;
import com.springboot.springbootlogindemo.domain.UserLikes;
import com.springboot.springbootlogindemo.mapper.ContentStatsMapper;
import com.springboot.springbootlogindemo.mapper.UserLikesMapper;
import com.springboot.springbootlogindemo.utils.Constants.RedisConstants;

import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component
public class LikeSyncScheduler {

    private static final Logger log = LoggerFactory.getLogger(LikeSyncScheduler.class);


    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private UserLikesMapper userLikesMapper;

    @Resource
    private ContentStatsMapper contentStatsMapper;

    @Scheduled(fixedRate = 5000) // 每隔5秒执行一次
    public void syncLikesToDatabase() {

        try {
            log.info("点赞信息同步DB任务开始");
            List<UserLikes> likesToSync = getLikedDataFromRedis();
            List<ContentStats> likedCountFromRedis = getLikedCountFromRedis();


            // 批量插入或更新到 MySQL
            for (UserLikes userLikes : likesToSync) {
                //先查看数据库里有无该记录
                UserLikes existingLike = userLikesMapper.selectOne(new QueryWrapper<UserLikes>().eq("info_id", userLikes.getInfoId()).eq("like_user_id", userLikes.getLikeUserId()));
                if (existingLike == null) {
                    userLikesMapper.insert(userLikes);
                } else {
                    existingLike.setStatus(userLikes.getStatus());
                    userLikesMapper.updateById(existingLike);
                }
            }

            for (ContentStats contentStats : likedCountFromRedis) {
                //先查看有无该数据,根据对象id查看
                ContentStats existingContentStats = contentStatsMapper.selectOne(new QueryWrapper<ContentStats>().eq("content_id", contentStats.getContentId()));
                if (existingContentStats == null) {
                    contentStatsMapper.insert(contentStats);

                } else {
                    existingContentStats.setLikeCount(contentStats.getLikeCount());
                    contentStatsMapper.updateById(contentStats);
                }
            }
            log.info("点赞信息同步DB任务结束");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 这个方法用来读取redis中所有的点赞记录，并转换成UserLikesDto返回，读取后会将redis中的记录删除
     *
     * @return
     */
    public List<UserLikesDto> getLikedDataDTOFromRedis() {
        //读取redis中的点赞记录
        Cursor<Map.Entry<Object, Object>> scan = redisTemplate.opsForHash().scan(RedisConstants.LIKED_RECORD, ScanOptions.NONE);
        List<UserLikesDto> list = new ArrayList<>();
        while (scan.hasNext()) {
            Map.Entry<Object, Object> entry = scan.next();
            String key = (String) entry.getKey();
            //获取点赞记录信息
            String[] split = key.split("::");
            Long infoId = Long.valueOf(split[0]);
            Long likeUserId = Long.valueOf(split[1]);
            Integer value = (Integer) entry.getValue();
            //组装成 UserLike 对象
            UserLikesDto userLikeDetail = new UserLikesDto(infoId, likeUserId, value);
            list.add(userLikeDetail);
            //存到 list 后从 Redis 中删除
            redisTemplate.opsForHash().delete(RedisConstants.LIKED_RECORD, key);
        }
        return list;
    }

    public List<UserLikes> getLikedDataFromRedis() {
        //读取redis中的点赞记录
        Cursor<Map.Entry<Object, Object>> scan = redisTemplate.opsForHash().scan(RedisConstants.LIKED_RECORD, ScanOptions.NONE);
        List<UserLikes> list = new ArrayList<>();
        while (scan.hasNext()) {
            Map.Entry<Object, Object> entry = scan.next();
            String key = (String) entry.getKey();
            //获取点赞记录信息
            String[] split = key.split("::");
            Long infoId = Long.valueOf(split[0]);
            Long likeUserId = Long.valueOf(split[1]);
            Integer value = (Integer) entry.getValue();
            //组装成 UserLike 对象
            UserLikes userLikes = new UserLikes();
            userLikes.setInfoId(infoId);
            userLikes.setLikeUserId(likeUserId);
            userLikes.setStatus(value);
            list.add(userLikes);
            //存到 list 后从 Redis 中删除
            redisTemplate.opsForHash().delete(RedisConstants.LIKED_RECORD, key);
        }
        return list;
    }


    /**
     * 这个方法用来读取redis中的所有点赞数量，并转换成UserLikCountDTO返回，读取后会将redis中的记录删除
     *
     * @return
     */
    public List<UserLikCountDTO> getLikedCountDTOFromRedis() {
        Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(RedisConstants.LIKED_COUNT, ScanOptions.NONE);
        List<UserLikCountDTO> list = new ArrayList<>();
        while (cursor.hasNext()) {
            Map.Entry<Object, Object> map = cursor.next();

            String key = (String) map.getKey();
            Integer value = (Integer) map.getValue();
            UserLikCountDTO userLikCountDTO = new UserLikCountDTO(key, value);
            list.add(userLikCountDTO);
            redisTemplate.opsForHash().delete(RedisConstants.LIKED_COUNT, key);
        }
        return list;
    }


    /**
     * 这个方法用来读取redis中的所有点赞数量，并转换成UserLikCountDTO返回，读取后会将redis中的记录删除
     *
     * @return
     */
    public List<ContentStats> getLikedCountFromRedis() {
        Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(RedisConstants.LIKED_COUNT, ScanOptions.NONE);
        List<ContentStats> list = new ArrayList<>();
        while (cursor.hasNext()) {
            Map.Entry<Object, Object> map = cursor.next();
            String key = (String) map.getKey();
            Integer value = (Integer) map.getValue();
            ContentStats contentStats = new ContentStats();
            contentStats.setContentId(Long.valueOf(key));
            contentStats.setLikeCount(value);
            list.add(contentStats);
            redisTemplate.opsForHash().delete(RedisConstants.LIKED_COUNT, key);
        }
        return list;
    }


}